package com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.nyk;

import com.alibaba.cirtus.ots.application.adapter.ability.facade.serviceV2.sap.MnSapIf008V2ServiceImpl;
import com.alibaba.cirtus.ots.application.adapter.ability.model.enums.NykFailRecordEnum;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.CodeUtil;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.InfoUtil;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.util.TimeUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByOutCodes2Request;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByOutCodes2Response;
import com.epoch.app.bcorder.model.dto.BaselineQueryScItemByPageRequest;
import com.epoch.app.bcorder.model.dto.OrganizationSDO;
import com.epoch.app.bcorder.model.dto.WarehouseInfo;
import com.epoch.app.bcorder.model.dto.WmsQueryWarehouseZoneListRequest;
import com.epoch.app.bcorder.model.dto.WmsQueryWarehouseZoneListResponse;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.crunifiedinventory.api.forecastwarehouse.dto.QueryWarehouseByFactoryCodeAndWarehouseCodeRequest;
import com.epoch.app.crunifiedinventory.api.forecastwarehouse.service.ForecastWarehouseService;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.AllocateOrderLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.CreateAllocateOrderResponse;
import com.epoch.app.crunifiedinventory.domain.allocateorder.dto.DeleteAllocateOrderRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorder.model.AllocateOrder;
import com.epoch.app.crunifiedinventory.domain.allocateorder.service.AllocateOrderService;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.AllocateOrderDetailLoadListRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.CreateAllocateOrderDetailResponse;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.dto.DeleteAllocateOrderDetailRequest;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.model.AllocateOrderDetail;
import com.epoch.app.crunifiedinventory.domain.allocateorderdetail.service.AllocateOrderDetailService;
import com.epoch.app.crunifiedinventory.model.dto.WarehouseInfoDTO;
import com.epoch.app.crunifiedinventory.model.enums.AllocateOrderStatus;
import com.epoch.app.crunifiedinventory.nykdatachecker.dto.StartProcessTransferOrdersRequest;
import com.epoch.app.crunifiedinventory.nykdatachecker.service.NykDataCheckerService;
import com.epoch.app.crunifiedinventory.ouinykfailrecord.model.OuiNykFailRecord;
import com.epoch.app.crunifiedinventory.ouinykfailrecord.service.OuiNykFailRecordService;
import com.epoch.app.crunifiedinventory.sdo.enums.AllocateOrderTypeEnum;
import com.epoch.app.otsapplicationadaptersdk.nyk.NykTransferOrder;
import com.epoch.app.otsapplicationadaptersdk.nyk.NykTransferOrderPageData;
import com.epoch.app.otsapplicationadaptersdk.nyk.NykTransferOrderResponse;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyktransferorder.dto.DoHandlerRequest;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyktransferorder.dto.DoHandlerResponse;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyktransferorder.dto.GetAllNykAllocateOrdersRequest;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyktransferorder.dto.GetAllNykAllocateOrdersResponse;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyktransferorder.dto.GetNykTransferOrdersByApiAdaptorRequest;
import com.epoch.app.otsapplicationadaptersdk.nyk.mnnyktransferorder.service.MnNykTransferOrderService;
import com.epoch.app.otsapplicationadaptersdk.service.NykService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author zhoubc
 * @description: 牛要客计划调拨数据同步， 主子单处理模式
 * @date 2021/11/8 22:56
 */
@Component
public class MnNykTransferOrderV2ServiceImpl implements MnNykTransferOrderService {
    private final Log log = Log.getLogger(MnNykTransferOrderV2ServiceImpl.class);
    private static final String NYK_OPERATOR = "0";

    @Resource
    private NykService nykService;

    @Resource
    private AllocateOrderService allocateOrderService;

    @Resource
    private AllocateOrderDetailService allocateOrderDetailService;

    @Resource
    private UnifiedInventoryService unifiedInventoryService;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private ForecastWarehouseService forecastWarehouseService;

    @Autowired
    private OuiNykFailRecordService ouiNykFailRecordService;

    @Autowired
    private NykDataCheckerService nykDataCheckToolService;

    @Resource(name = "nykSynTaskExecutor")
    private ThreadPoolTaskExecutor nykSynTaskExecutor;

    private void createErrorLog(String failureReason, NykTransferOrder record, DoHandlerRequest doHandlerRequest) {
        OuiNykFailRecord request = new OuiNykFailRecord();
        request.setFeatures(JSONObject.toJSONString(record));
        request.setFailureReason(failureReason);
        request.setQueryRequest(JSONObject.toJSONString(doHandlerRequest));
        request.setType(NykFailRecordEnum.TRANSFER.getValue());
        request.setSubId(record.getLineNo());
        request.setOrderId(record.getSapCode());
        ouiNykFailRecordService.create(request);
    }

    @Override
    @ProcessInvoker
    public DoHandlerResponse doHandler(DoHandlerRequest doHandlerRequest) {
        GetNykTransferOrdersByApiAdaptorRequest request = buildRequest(doHandlerRequest);
//        NykTransferOrderResponse response = nykService.restNykTransferOrderData(request);
        //修改为通过集成平台获取牛要客调拨单
        NykTransferOrderResponse response = getNykTransferOrdersByApiAdaptor(request);

        DoHandlerResponse doHandlerResponse = new DoHandlerResponse();
        // 检验 拉取数据是否成功
        String errorMessage = checkResponse(response);
        if (StringUtils.isNotBlank(errorMessage)) {
            doHandlerResponse.setSuccess(false);
            doHandlerResponse.setMessage(errorMessage);
            return doHandlerResponse;
        }

        Integer successNum = 0;
        Integer failNum = 0;

        BaselineGetOrganizationByOutCodes2Request organizationRequest =
                BaselineGetOrganizationByOutCodes2Request.builder().outCodes(Arrays.asList("6140")).status(1).build();
        BaselineGetOrganizationByOutCodes2Response baselineGetOrganizationByOutCodes2Response = baseDataService.baselineGetOrganizationByOutCodes2(organizationRequest);
        //2022.03.16 提报组织id为分子公司层级
        OrganizationSDO organizationSDO = baselineGetOrganizationByOutCodes2Response.getResult().get(0);
        String applyOrgId = organizationSDO.getId();
        if (Objects.equals(organizationSDO.getType(),104)){
            applyOrgId = organizationSDO.getParentId();
        }
        //        String applyOrgId = baselineGetOrganizationByOutCodes2Response.getResult().get(0).getId();
        String batchNo= nykDataCheckToolService.generateBatchNo().getBatchNo();
        for (int i = 1; i <= response.getData().getPages(); i++) {

            request.setCurrent(String.valueOf(i));
//            NykTransferOrderResponse pageResponse = nykService.restNykTransferOrderData(request);
            NykTransferOrderResponse pageResponse = getNykTransferOrdersByApiAdaptor(request);
            log.info("getNykTransferOrdersByApiAdaptor, response_info:{}", JSONObject.toJSONString(pageResponse));
            saveProcessLogToCheckTool(batchNo, pageResponse, request.getQueryDate());
            List<NykTransferOrder> records = pageResponse.getData().getRecords();
            if (CollectionUtils.isEmpty(records)) {
                log.error("getNykTransferOrdersByApiAdaptor, error， req:{}", JSON.toJSONString(pageResponse));
                continue;
            }
            Map<String, Integer> map = syncCurrentPage(records, applyOrgId, doHandlerRequest);
            successNum = successNum + map.get("successNum");
            failNum = failNum + map.get("failNum");
        }

        doHandlerResponse.setSuccess(true);
        doHandlerResponse.setMessage("同步完成");
        doHandlerResponse.setResult(response);
        doHandlerResponse.setSuccessNum(successNum);
        doHandlerResponse.setFailNum(failNum);
        return doHandlerResponse;
    }

    @Override
    public GetAllNykAllocateOrdersResponse getAllNykAllocateOrders(GetAllNykAllocateOrdersRequest getAllNykAllocateOrdersRequest){
        GetAllNykAllocateOrdersResponse response = new GetAllNykAllocateOrdersResponse();
        String endDate = getAllNykAllocateOrdersRequest.getEndDate();
        if (StringUtils.isBlank(endDate)){
            endDate=String.valueOf(LocalDate.now());;
        }
        List<String> dateList = collectLocalDates(getAllNykAllocateOrdersRequest.getStartDate(), endDate);

        DoHandlerRequest doHandlerRequest = new DoHandlerRequest();

        for (String oneDay : dateList) {
            doHandlerRequest.setQueryDate(oneDay);
            doHandlerRequest.setSize("500");
            DoHandlerResponse handlerResponse = doHandler(doHandlerRequest);
            response.setSuccessCount(String.valueOf(handlerResponse.getSuccessNum()));
        }
        return response;
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param timeStart
     * @param timeEnd
     * @return
     */
    private static List<String> collectLocalDates(String timeStart, String timeEnd) {
        return collectLocalDates(LocalDate.parse(timeStart), LocalDate.parse(timeEnd));
    }

    /**
     * 收集起始时间到结束时间之间所有的时间并以字符串集合方式返回
     *
     * @param start
     * @param end
     * @return
     */
    private static List<String> collectLocalDates(LocalDate start, LocalDate end) {
        // 用起始时间作为流的源头，按照每次加一天的方式创建一个无限流
        return Stream.iterate(start, localDate -> localDate.plusDays(1))
                // 截断无限流，长度为起始时间和结束时间的差+1个
                .limit(ChronoUnit.DAYS.between(start, end) + 1)
                // 由于最后要的是字符串，所以map转换一下
                .map(LocalDate::toString)
                // 把流收集为List
                .collect(Collectors.toList());
    }

    /**
     * 组装 拉取牛要客调拨单 请求参数
     *
     * @param doHandlerRequest
     * @return
     */
    private GetNykTransferOrdersByApiAdaptorRequest buildRequest(DoHandlerRequest doHandlerRequest) {
        GetNykTransferOrdersByApiAdaptorRequest restNykTransferOrderDataRequest = new GetNykTransferOrdersByApiAdaptorRequest();
        restNykTransferOrderDataRequest.setCurrent(doHandlerRequest.getCurrent());
        restNykTransferOrderDataRequest.setSize(doHandlerRequest.getSize());
        if (StringUtils.isNotBlank(doHandlerRequest.getQueryDate())) {
            restNykTransferOrderDataRequest.setQueryDate(doHandlerRequest.getQueryDate());
        }
        return restNykTransferOrderDataRequest;
    }

    /**
     * 检验 拉取数据是否成功
     *
     * @param response
     * @return
     */
    private String checkResponse(NykTransferOrderResponse response) {
        if (Objects.isNull(response)) {
            return "没有查到牛要客同步数据";
        }
        if (response.getSuccess() == null) {
            return "查询牛要客数据失败,message：" + response.getMsg();
        }
        if (!response.getSuccess()) {
            return "查询牛要客数据失败,message：" + response.getMsg();
        }

        NykTransferOrderPageData data = response.getData();
        if (Objects.isNull(data) || CollectionUtils.isEmpty(data.getRecords())) {
            return "查询牛要客数据失败,message：" + response.getMsg();
        }
        return null;
    }

    private Map<String, Integer> syncCurrentPage(List<NykTransferOrder> records, String applyOrgId, DoHandlerRequest doHandlerRequest) {
        AtomicReference<Integer> successNum = new AtomicReference<>(0);
        AtomicReference<Integer> failNum = new AtomicReference<>(0);

        Map<String, List<NykTransferOrder>> mainGroup = Optional.ofNullable(records).orElse(Lists.newArrayList()).stream().collect(Collectors.groupingBy(NykTransferOrder::getSapCode));
        List<CompletableFuture<String>> futures = Lists.newArrayList();
        for (Map.Entry<String, List<NykTransferOrder>> entry : mainGroup.entrySet()) {
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                try {
                    dealMainOrder(applyOrgId, doHandlerRequest, successNum, failNum, entry);
                } catch (Exception e) {
                    log.error(e, "同步牛要客调拨单数据失败, headkey: {}", entry.getKey());
                }
                return entry.getKey();
            }, nykSynTaskExecutor);

            futures.add(future);
        }

        for (CompletableFuture<String> future : futures) {
            try {
                String record = future.get();
                log.info("NykTransferOrder create sync success headerKey = {}", record);
            } catch (Exception e) {
                log.error(e, "NykTransferOrder create sync error");
            }
        }

        Map<String, Integer> map = new HashMap<String, Integer>() {{
            put("successNum", successNum.get());
            put("failNum", failNum.get());
        }};
        return map;
    }

    private void dealMainOrder(String applyOrgId, DoHandlerRequest doHandlerRequest, AtomicReference<Integer> successNum, AtomicReference<Integer> failNum, Map.Entry<String, List<NykTransferOrder>> entry) {
        AllocateOrder mainAllocateOrder = null;
        List<NykTransferOrder> subRecords = Optional.ofNullable(entry.getValue()).orElse(Lists.newArrayList());

        // 判断调拨单是否已存在
        AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
        allocateOrderLoadListRequest.setOutAllocateOrderId(entry.getKey());
        Result<List<AllocateOrder>> loadAllocateOrderList = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
        if (loadAllocateOrderList != null && CollectionUtils.isNotEmpty(loadAllocateOrderList.getResult()) && loadAllocateOrderList.getResult().get(0) != null) {
            mainAllocateOrder = loadAllocateOrderList.getResult().get(0);
            mainAllocateOrder = deleteAllocateOrder(mainAllocateOrder, subRecords);
        }

        for (NykTransferOrder nykTransferOrder : subRecords) {
            try {
                // 校验参数
                String check = check(nykTransferOrder);
                if (StringUtils.isNotBlank(check)) {
                    log.error("同步牛要客调拨单数据失败，缺少参数 :{}， request: {}", check, JSONObject.toJSONString(nykTransferOrder));
                    failNum.getAndSet(failNum.get() + 1);
                    createErrorLog("同步牛要客调拨单数据失败，缺少参数" + check, nykTransferOrder, doHandlerRequest);
                    continue;
                }

                String code = CodeUtil.getCode(AllocateOrderTypeEnum.PLAN.getType());
                Boolean addFlag = false;
                // 如果 调拨单主单不存在 则新增调拨单主单
                if (mainAllocateOrder == null || mainAllocateOrder.getId() == null) {
                    // 调拨单 新增
                    mainAllocateOrder = new AllocateOrder();

                    // 本系统字段意思 牛要客字段意思
                    // 外部单号     主单id
                    //20220107 修改为sapCode
                    mainAllocateOrder.setOutAllocateOrderId(nykTransferOrder.getSapCode());
                    //设置nykId 用来判别当前订单是否牛要客订单
                    mainAllocateOrder.setNykId(nykTransferOrder.getSapCode());

                    // 提报组织     默认6140对应组织
                    mainAllocateOrder.setApplyOrgId(applyOrgId);
                    // 调拨类型     默认计划调拨
                    mainAllocateOrder.setType(AllocateOrderTypeEnum.PLAN.getType());
                    // 产品组      常温11
                    mainAllocateOrder.setProductGroup("11");
                    // 单据状态     默认已收货
                    mainAllocateOrder.setStatus(AllocateOrderStatus.Received.getValue());
                    // 是否直发客户   默认否
                    mainAllocateOrder.setIsDTC(false);
                    // 是否退单     是否退单
                    mainAllocateOrder.setReturnOrder(StringUtils.isBlank(nykTransferOrder.getDedi6()) ? null : nykTransferOrder.getDedi6().equals("true") ? true : false);

                    // 查询收货仓 入参
                    // 收货工厂代码
                    String distPoint = nykTransferOrder.getWhseCode();
                    // 库存地点
                    String whseCode = StringUtils.defaultIfBlank(nykTransferOrder.getDistPoint(), "DEFAULT");
                    // 查询收货仓 TODO 先默认写死走流程 I029 R011
                    WmsQueryWarehouseZoneListRequest zoneListRequest = new WmsQueryWarehouseZoneListRequest();
                    zoneListRequest.setWarehouseCode(whseCode);
                    zoneListRequest.setSapFactoryCode(distPoint);
                    WmsQueryWarehouseZoneListResponse receiveResponse = unifiedInventoryService.wmsQueryWarehouseZoneList(zoneListRequest);
                    if (ObjectUtils.isEmpty(receiveResponse) || (!ObjectUtils.isEmpty(receiveResponse) && CollectionUtils.isEmpty(receiveResponse.getResult()))) {
                        log.error("同步牛要客调拨单数据失败，查询收货仓库不存在 request:{}", JSONObject.toJSONString(nykTransferOrder));
                        failNum.getAndSet(failNum.get() + 1);
                        createErrorLog("同步牛要客调拨单数据失败，查询收货仓库不存在 , 库存地点 = "
                                        + whseCode + " | 收货工厂代码 = " + distPoint
                                , nykTransferOrder, doHandlerRequest);
                        continue;
                    }
                    String receiveAreaId = MnSapIf008V2ServiceImpl.getAreaId(receiveResponse);
                    String receiveWarehouseId = MnSapIf008V2ServiceImpl.getWarehouseId(receiveResponse);
                    // 收货仓
                    mainAllocateOrder.setReceiveWarehouseId(receiveWarehouseId);
                    // 收货仓-库区
                    mainAllocateOrder.setReceiveAreaId(receiveAreaId);
                    // 收货组织
                    String saleOrgId = getSaleOrgId(receiveResponse);
                    mainAllocateOrder.setReceiveOrgId(saleOrgId);

                    // 查询发货仓 入参
                    // 发货工厂代码
                    String factoryCode = nykTransferOrder.getFactoryCode();
                    String distLocation = StringUtils.defaultIfBlank(nykTransferOrder.getDistLocation(), "DEFAULT");
                    if (StringUtils.isNotBlank(factoryCode)) {
                        //收货id 根据工厂和库存code查找
                        QueryWarehouseByFactoryCodeAndWarehouseCodeRequest queryWarehouseByFactoryCodeAndWarehouseCodeRequest = new QueryWarehouseByFactoryCodeAndWarehouseCodeRequest();
                        queryWarehouseByFactoryCodeAndWarehouseCodeRequest.setWarehouseCode(distLocation);
                        queryWarehouseByFactoryCodeAndWarehouseCodeRequest.setFactoryCode(factoryCode);
                        Result<List<WarehouseInfoDTO>> listResult = forecastWarehouseService.queryWarehouseByFactoryCodeAndWarehouseCode(queryWarehouseByFactoryCodeAndWarehouseCodeRequest);
                        //收货仓库
                        if (Objects.nonNull(listResult) && CollectionUtils.isNotEmpty(listResult.getResult())) {
                            WarehouseInfoDTO warehouseInfoDTO = listResult.getResult().get(0);
                            // 发货仓
                            mainAllocateOrder.setShipWarehouseId(warehouseInfoDTO.getWarehouseId());
                            // 发货仓-库区
                            mainAllocateOrder.setShipAreaId(warehouseInfoDTO.getId());
                            // 发货组织
                            mainAllocateOrder.setShipOrgId(warehouseInfoDTO.getSaleOrgId());
                        } else {
                            log.error("同步牛要客调拨单数据失败，查询发货仓库不存在 request:{}", nykTransferOrder);
                            failNum.getAndSet(failNum.get() + 1);
                            createErrorLog("同步牛要客调拨单数据失败，查询发货仓库不存在 , 工厂编码 = " + factoryCode +
                                            " | 库存地点 = " + distLocation
                                    , nykTransferOrder, doHandlerRequest);
                            continue;
                        }
                    } else {
                        log.error("同步牛要客调拨单数据失败，工厂code为空！");
                        failNum.getAndSet(failNum.get() + 1);
                        createErrorLog("同步牛要客调拨单数据失败，工厂code为空", nykTransferOrder, doHandlerRequest);
                        continue;
                    }

                    // 装运方式   装运条件
                    mainAllocateOrder.setShipMethod(nykTransferOrder.getShipment() == null ? null : Integer.valueOf(nykTransferOrder.getShipment()));

                    // feature放来源
                    Map<String, String> map = new HashMap<String, String>() {{
                        put("source", "nyk");
                    }};
                    mainAllocateOrder.setFeatures(JSONObject.toJSONString(map));

                    mainAllocateOrder.setCode(code);
                    mainAllocateOrder.setRemark(nykTransferOrder.getLineNo());
                    mainAllocateOrder.setGmt_create(TimeUtil.getDateByLong(nykTransferOrder.getCreateTime()));
                    mainAllocateOrder.setCreator(NYK_OPERATOR);
                    mainAllocateOrder.setUpdater(NYK_OPERATOR);
                    log.info("MnNykTransferOrderServiceImpl, createAllocateOrder {}", JSONObject.toJSONString(mainAllocateOrder));
                    CreateAllocateOrderResponse orderResponse = allocateOrderService.createAllocateOrder(mainAllocateOrder);
                    if (Objects.isNull(orderResponse) || Objects.isNull(orderResponse.getLastInsertId())) {
                        log.error("createAllocateOrder create fail = allocateOrder {} , orderResponse {}", mainAllocateOrder, orderResponse);
                        log.error("MnNykTransferOrderServiceImpl.syncCurrentPage_fail");
                        createErrorLog("主单保存失败", nykTransferOrder, doHandlerRequest);
                        continue;
                    }
                    mainAllocateOrder.setId(orderResponse.getLastInsertId());
                }

                if (mainAllocateOrder == null || mainAllocateOrder.getId() == null) {
                    log.error("主单创建失败, {}", JSON.toJSONString(mainAllocateOrder));
                    createErrorLog("主单创建失败", nykTransferOrder, doHandlerRequest);
                    continue;
                }

                // 查询子单
                AllocateOrderDetail subOrder = null;
                AllocateOrderDetailLoadListRequest r = new AllocateOrderDetailLoadListRequest();
                r.setAllocateOrderId(mainAllocateOrder.getId());
                r.setOutAllocateOrderLineId(nykTransferOrder.getLineNo());
                Result<List<AllocateOrderDetail>> loadAllocateOrderDetailList = allocateOrderDetailService.loadAllocateOrderDetailList(r);
                log.info("MnNykTransferOrderServiceImpl, check result:" + JSON.toJSONString(entry) + ",REQ:" + JSON.toJSONString(r) + ",REP:" + JSON.toJSONString(loadAllocateOrderDetailList));
                if (loadAllocateOrderDetailList != null && CollectionUtils.isNotEmpty(loadAllocateOrderDetailList.getResult()) && loadAllocateOrderDetailList.getResult().get(0) != null) {
                    subOrder = loadAllocateOrderDetailList.getResult().get(0);
                }

                if (subOrder != null) {
                    createErrorLog("子单已存在", nykTransferOrder, doHandlerRequest);
                    continue;
                }

                // 如果 主单存在 且 调拨单明细不存在 则新增 调拨单明细
                if (subOrder == null) {
                    // 调拨单明细 新增
                    AllocateOrderDetail allocateOrderDetail = new AllocateOrderDetail();
                    // 本系统字段意思 牛要客字段意思
                    // 外部行号     子单id
                    //20220207 修改为lineNo
                    allocateOrderDetail.setOutAllocateOrderLineId(nykTransferOrder.getLineNo());
                    // 调拨单id
                    allocateOrderDetail.setAllocateOrderId(mainAllocateOrder.getId());
                    // 调拨类型     默认计划调拨
                    allocateOrderDetail.setType(AllocateOrderTypeEnum.PLAN.getType());
                    // 行状态     已收货
                    allocateOrderDetail.setStatus(AllocateOrderStatus.Received.getValue());
                    // 货品编码    物料号码
                    allocateOrderDetail.setScItemCode(deleteZeroPrefix(nykTransferOrder.getItemCode()));
                    // 货品id
                    String scItemId = InfoUtil.getScItemIdByOutCode(deleteZeroPrefix(nykTransferOrder.getItemCode()));
                    allocateOrderDetail.setScItemId(scItemId);
                    // 货品名称 自动带出
                    allocateOrderDetail.setScItemName(getItNameByOutCode(allocateOrderDetail.getScItemCode()));
                    // 数量       确认数量
                    //20220107 修改为salesNum
                    allocateOrderDetail.setQuantity(nykTransferOrder.getSalesNum() + "");
//                    allocateOrderDetail.setQuantity(ObjectUtils.isEmpty(nykTransferOrder.getCfmNum()) ? null : nykTransferOrder.getCfmNum().toString());
                    // 单位 自动带出
                    allocateOrderDetail.setUnit(getUnitByOutCode(allocateOrderDetail.getScItemCode()));
                    // 单价       单价
                    allocateOrderDetail.setPrice(nykTransferOrder.getNetPrice().toString());
                    // 折后金额 数量*单价
                    String discountAmount = null;
                    //确认数量
                    //20220107 新增字段
                    allocateOrderDetail.setConfirmQuantity(nykTransferOrder.getCfmNum() + "");
                    //出库数量
                    //20220107 新增字段 出库数量
                    allocateOrderDetail.setShipQuantity(nykTransferOrder.getDelyNum());
                    //交货日期
                    //20220107 新增字段 交货日期
                    SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    allocateOrderDetail.setDeliveryDate(StringUtils.isBlank(nykTransferOrder.getDelyDate()) ? null :
                            simpleDate.parse(parseDate(nykTransferOrder.getDelyDate())));
                    if (nykTransferOrder.getCfmNum() != null) {
                        discountAmount = nykTransferOrder.getNetPrice().multiply(new BigDecimal(nykTransferOrder.getCfmNum())).toString();
                    }
                    allocateOrderDetail.setDiscountAmount(discountAmount);
                    allocateOrderDetail.setSubTotalAmount(discountAmount);
                    // 期望生产日期   需求者/请求者姓名(生产日期）
//                    allocateOrderDetail.setExpectedProduceDate(TimeUtil.parseTime(this.parseDate(nykTransferOrder.getPriceDate())));
                    // 创建时间（行） 创建时间
                    allocateOrderDetail.setGmt_create(TimeUtil.getDateByLong(nykTransferOrder.getCreateTime()));
                    allocateOrderDetail.setCreator(NYK_OPERATOR);
                    allocateOrderDetail.setUpdater(NYK_OPERATOR);
                    nykTransferOrder.setId(null);
                    allocateOrderDetail.setFeatures(JSONObject.toJSONString(nykTransferOrder));
                    allocateOrderDetail.setAllocateOrderCode(mainAllocateOrder.getCode());
                    log.info("MnNykTransferOrderServiceImpl, createAllocateOrderDetail {}", JSONObject.toJSONString(allocateOrderDetail));
                    CreateAllocateOrderDetailResponse detailResponse = allocateOrderDetailService.createAllocateOrderDetail(allocateOrderDetail);
                    if (Objects.isNull(detailResponse) || StringUtils.isBlank(detailResponse.getLastInsertId())) {
                        log.error("MnNykTransferOrderServiceImpl, create fail = allocateOrderDetail {} detailResponse {}", allocateOrderDetail, detailResponse);
                        log.error("MnNykTransferOrderServiceImpl, syncCurrentPage_fail");
                        createErrorLog("子单保存失败", nykTransferOrder, doHandlerRequest);
                    }
                    addFlag = true;
                }
                log.info("MnNykTransferOrderServiceImpl, deal result: {}", JSONObject.toJSONString(nykTransferOrder));
                if (addFlag) {
                    successNum.getAndSet(successNum.get() + 1);
                }
            } catch (Exception e) {
                log.error(e, "同步牛要客调拨单数据失败, request: {}", JSONObject.toJSONString(nykTransferOrder));
                failNum.getAndSet(failNum.get() + 1);
                createErrorLog("系统异常", nykTransferOrder, doHandlerRequest);
            }

        }
    }

    private String parseDate(String date) {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        //数据格式不为20210101不处理
        if (date.length() != 8) {
            return null;
        }
        String year = date.substring(0, 4);
        String mon = date.substring(4, 6);
        String day = date.substring(6, date.length());
        return year + "-" + mon + "-" + day + " 00:00:00";
    }

    private String getName(WmsQueryWarehouseZoneListResponse response) {
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())) {
            WarehouseInfo warehouseInfo = response.getResult().get(0);
            return warehouseInfo.getName();
        }
        return null;
    }

    private String getSaleOrgId(WmsQueryWarehouseZoneListResponse response) {
        if (response != null && CollectionUtils.isNotEmpty(response.getResult())) {
            WarehouseInfo warehouseInfo = response.getResult().get(0);
            return warehouseInfo.getSapSaleOrgId();
        }
        return null;
    }

    private String getUnitByOutCode(String outCode) {
        String code = deleteZeroPrefix(outCode);
        if (StringUtils.isNotBlank(code)) {
            BaselineQueryScItemByPageRequest baselineQueryScItemByPageRequest = new BaselineQueryScItemByPageRequest();
            baselineQueryScItemByPageRequest.setOutIdList(Lists.newArrayList(code));
            Object obj = baseDataService.baselineQueryScItemByPage(baselineQueryScItemByPageRequest);
            if (obj != null) {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(obj));
                if (jsonObject != null) {
                    jsonObject = jsonObject.getJSONObject("result");
                    if (jsonObject != null) {
                        jsonObject = jsonObject.getJSONObject("result");
                        if (jsonObject != null) {
                            JSONArray array = jsonObject.getJSONArray("searchResult");
                            if (array != null && array.size() > 0) {
                                jsonObject = array.getJSONObject(0).getJSONObject("features");
                                if (jsonObject != null) {

                                    return jsonObject.getString("unitName");
                                }
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    private String getItNameByOutCode(String outCode) {
        String code = deleteZeroPrefix(outCode);
        if (StringUtils.isNotBlank(code)) {
            BaselineQueryScItemByPageRequest baselineQueryScItemByPageRequest = new BaselineQueryScItemByPageRequest();
            baselineQueryScItemByPageRequest.setOutIdList(Lists.newArrayList(code));
            Object obj = baseDataService.baselineQueryScItemByPage(baselineQueryScItemByPageRequest);
            if (obj != null) {
                JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(obj));
                if (jsonObject != null) {
                    jsonObject = jsonObject.getJSONObject("result");
                    if (jsonObject != null) {
                        jsonObject = jsonObject.getJSONObject("result");
                        if (jsonObject != null) {
                            JSONArray array = jsonObject.getJSONArray("searchResult");
                            if (array != null && array.size() > 0) {
                                Object title = array.getJSONObject(0).get("title");
                                if (title != null) {
                                    return title.toString();
                                }
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * 保存业务处理日志，用于数据核对
     * @param batchNo
     * @param tmpResp
     */
    private void saveProcessLogToCheckTool(String batchNo, NykTransferOrderResponse tmpResp, String queryDate) {
        StartProcessTransferOrdersRequest logRequest = new StartProcessTransferOrdersRequest();
        logRequest.setBatchNo(batchNo);
        logRequest.setResponseJson(JSONObject.toJSONString(tmpResp));
        logRequest.setCount(tmpResp.getData().getRecords().size());
        logRequest.setTime(DateTime.now().toDate());
        logRequest.setQueryDate(queryDate);

        nykDataCheckToolService.startProcessTransferOrders(logRequest);
    }


    public static String deleteZeroPrefix(String str) {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        return str.replaceFirst("^0*", "");
    }

    private String check(NykTransferOrder sdo) {
        if (StringUtils.isBlank(sdo.getSapCode())) {
            return "SapCode 不能为空";
        }
        if (StringUtils.isBlank(sdo.getWhseCode())) {
            return "whseCode 不能为空";
        }
        if (StringUtils.isBlank(sdo.getDistPoint())) {
            return "distPoint 不能为空";
        }
        if (StringUtils.isBlank(sdo.getFactoryCode())) {
            return "factoryCode 不能为空";
        }
        //20220107修改为lineNo，不需要此字段
//        if (StringUtils.isBlank(sdo.getInfoId())) {
//            return "infoId 不能为空";
//        }
        if (StringUtils.isBlank(sdo.getItemCode())) {
            return "itemCode 不能为空";
        }
        if (ObjectUtils.isEmpty(sdo.getCfmNum())) {
            return "cfmNum 不能为空";
        }
        if (ObjectUtils.isEmpty(sdo.getNetPrice())) {
            return "netPrice 不能为空";
        }
        return null;
    }


    //删除主单中已存在的子单，如果子单删光了就把主单也删掉
    private AllocateOrder deleteAllocateOrder(AllocateOrder mainOrder, List<NykTransferOrder> subOrders) {
        if (mainOrder == null || CollectionUtils.isEmpty(subOrders)) {
            return mainOrder;
        }

        // 查询主单的子单列表
        AllocateOrderDetailLoadListRequest request = new AllocateOrderDetailLoadListRequest();
        request.setAllocateOrderId(mainOrder.getId());
        Result<List<AllocateOrderDetail>> detailList = allocateOrderDetailService.loadAllocateOrderDetailList(request);
        Map<String, List<AllocateOrderDetail>> outLineDetailMap = Maps.newHashMap();
        if (detailList != null && CollectionUtils.isNotEmpty(detailList.getResult())) {
            outLineDetailMap = detailList.getResult().stream().collect(Collectors.groupingBy(o->deleteZeroPrefix(o.getOutAllocateOrderLineId())));
        }

        for (NykTransferOrder subOrder : subOrders) {
            String outLineNo = deleteZeroPrefix(subOrder.getLineNo());
            List<AllocateOrderDetail> orderDetails = Optional.ofNullable(outLineDetailMap.get(outLineNo)).orElse(Lists.newArrayList());
            for (AllocateOrderDetail orderDetail : orderDetails) {
                DeleteAllocateOrderDetailRequest req = new DeleteAllocateOrderDetailRequest();
                req.setId(String.valueOf(orderDetail.getId()));
                allocateOrderDetailService.deleteAllocateOrderDetail(req);
            }

            outLineDetailMap.remove(outLineNo);
        }

        if (MapUtils.isEmpty(outLineDetailMap)) {
            DeleteAllocateOrderRequest deleteAllocateOrderRequest = new DeleteAllocateOrderRequest();
            deleteAllocateOrderRequest.setId(String.valueOf(mainOrder.getId()));
            allocateOrderService.deleteAllocateOrder(deleteAllocateOrderRequest);

            return null;
        }

        return mainOrder;

    }

}
